<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <!-- 
    this的指向

        1. 一般情况下(命名函数,匿名函数) this->window  严格模式下 this -> undefined

        2. 函数在调用时属于谁就指向谁     (a btn.onclick   b obj.say)

        3. ES6箭头函数，没有自己的this指向,它的this依赖于箭头函数所在作用域的 this
        
        4. 构造函数中this,指向函数在调用时创建的实例化对象

     -->

</body>
<script>
    // call apply bind  => 所有的函数均可以使用的方法
    // 作用：调用函数，改变this的指向

    // call 和 apply 调用函数 在函数执行过程中 强制将函数中的 this 指向 call/apply ()方法中的第一个参数(如果第一个参数是 null 或 undefined this指向不改变)

    // bind  并不会立即执行原函数，而是生成一个新函数，新函数执行过程中，强制将函数中的this指向bind()方法中的第一个参数(参数可以一次传入，也可在调用时传入)


    // call(obj,arg1,arg2,arg3...argN)   作用

    // 1.调用函数
    // 2.在函数执行过程中 强制将函数中的 this 指向 call()方法中的第一个参数(如果第一个参数是 null 或 undefined this指向不改变)
    // 3.如果函数需要接收参数，那么自第二参数开始依次按顺序传入

    function fn(a, b) {
        console.log(this);
        return a + b;
    }
    console.log(fn(1, 2));;               // this -> window
    console.log(fn.call(1, 2));           // this -> window
    console.log(fn.call(1, 1, 2));        // this -> Number
    console.log(fn.call(document, 1, 2));;  // this -> #document


    // apply(obj,arg1,arg2,arg3...argN)   作用

    // 1.调用函数
    // 2.在函数执行过程中 强制将函数中的 this 指向 call()方法中的第一个参数(如果第一个参数是 null 或 undefined this指向不改变)
    // 3.如果函数需要接收参数，需要先将参数依次按顺序放在数组中，再将参数作为第二参数传入


    function fn(a, b) {
        console.log(this);
        return a + b;
    }
    console.log(fn(10, 20));;               // this -> window
    console.log(fn.apply());           // this -> window
    console.log(fn.apply(1, [10, 20]));        // this -> Number
    console.log(fn.apply(document, [10, 20]));;  // this -> #document


    // bind(obj,arg1,arg2,arg3...argN)   作用

    // 1.不会立即指向函数，而是通过原函数生成一个新函数
    // 2.新函数在执行过程中，强制将函数中的this指向 bind()方法中的第一个参数(如果第一个参数是 null 或 undefined this指向不改变)
    // 3.如果函数需要接收参数
    // (1) bind 在调用过程中，自第二参数开始依次按顺序传入   => 参数被定死了
    // var f = fn.bind(document,100,200);
    // (2) 新函数在调用过程中，依次按顺序传入   => 参数可变
    // var f = fn.bind(document);
    // f(100,200);
    // f(6,9)


    function fn(a, b) {
        console.log(this);
        return a + b;
    }
    console.log(fn(100, 200));;               // this -> window
    var f = fn.bind(document);
    console.log(f(100, 200));               // this -> #document
    console.log(f === fn);   // false



</script>

</html>